namespace GYLite
{    
    export class Thread{        
        public static threads:{[id:number]:Thread} = {};
        public static idc:number=0;
        /**执行线程函数
         * @param id 线程id 固定线程参考ThreadID常量，如果传入-1，则创建一个唯一的id，注意自动创建id需要管理返回的线程避免内存泄露
         * @param threadFun 线程函数，线程函数的编写参考底部注释说明
         * @param threadFunParams 线程函数的传入参数数组，默认null
         * @param callBack 执行结束的回调，默认null
         * @param thisObj 线程函数和结束回调的this，默认null
         * @param immediate 是否立即执行
        */
        public static runThread(id:number, threadFun:Function, threadObj:any, threadFunParams:any[]=null, callBack:Function=null, thisObj:any=null, immediate:boolean=true):Thread
        {
            let s = this;
            let thread:Thread;
            id = id == -1?CommonUtil.loopTime + (++Thread.idc):id;
            thread = Thread.getThread(id);
            thread.reset(threadFun, threadObj, threadFunParams, 1);            
            thread.setCallBack(callBack, thisObj);
            if(immediate)
                thread.run();
            return thread;
        }
        /**是否存在线程
         * @param id 线程id 参考ThreadID常量
         * @return 存在则返回线程
         */
         public static hasThread(id:number):Thread
         {
            return Thread.threads[id];
         }
        /**获取线程
         * @param id 线程id 参考ThreadID常量
         */
        public static getThread(id:number):Thread
        {
            if(Thread.threads[id] == null)
                Thread.threads[id] = new Thread(id);                
            return Thread.threads[id];
        }
        private _globalThis;
        private _func:Function;
        public varObj:any;
        private _params:any[];
        private _cpuTime:number;
        private _destroyed:boolean;
        private _excCall:Function;
        private _excCallObj:any;
        private _excTime:number;
        private _subThread:Thread[];    
        private _inited:boolean;    
        private _runStartTime:number;
        private _costTime:number;
        private _id:number;
        private _running:boolean;
        private _parentThread:Thread;        
        public isEnd:boolean;
        public returnValue:any;
        public step:number;
        private _timeId:number;
        constructor(id:number,parentThread:Thread=null)
        {
            let s = this;
            s._id = id;
            s._parentThread = parentThread;
        }
        public reset(func:Function, thisObj:any, params:any[]=null,cpuTime:number = 3):void
        {
            let s = this;
            s.clear();
            s._func = func;
            s._globalThis = thisObj;
            s._params = params?params:[];
            s._params.push(s);            
            s._cpuTime = cpuTime;     
            s._subThread = [];                 
            s.step = 0;
        }
        /**运行线程*/
        public run():void
        {
            let s = this;
            if(s._running)return;
            s._running = true;
            s._runStartTime = Date.now();
            s.next();            
        }
        /**设置线程结束回调*/
        public setCallBack(callBack:Function, callBackObj:any):void
        {
            let s = this;
            s._excCall = callBack;
            s._excCallObj = callBackObj;
        }
        /**运行一个子级线程
         * @param index 线程索引
         * @param func 线程方法
         * @param thisObj 线程方法的this对象
         * @param params 线程方法的参数
         * @param cpuTime 线程方法每帧占用的cpu时间片
         * @return 运行成功
        */
        public runSubThread(index:number, func:Function, thisObj:any, params:any[]=null,cpuTime:number = 3):boolean
        {
            let s= this;
            let thread:Thread;            
            if(s._subThread[index] == null)
            {
                thread = new Thread(1000000+s._id,s);                              
                s._subThread[index] = thread;                
            } 
            else
                thread = s._subThread[index];   
            if(!thread._running)//未执行，执行一下
            {
                thread.reset(func,thisObj,params, cpuTime);
                thread.run();
                if(s._timeId > -1)
                {
                    TimeManager.unTimeOut(s._timeId, s.next, s);//进入子级线程执行，父级暂停
                    s._timeId = -1;
                }                
                return true;
            }
            return false;
        }
        /**获取子级线程
         * @param index 子级线程下标id
        */
        public getSubThread(index:number):Thread
        {
            return this._subThread[index];
        }
        /**清理所有子级线程
         * @param indexArr 指定清理的子级线程下标id数组，默认null，清理所有
        */
        public clearSubThread(indexArr:number[]=null):void
        {
            let s= this;
            let len:number;
            if(s._subThread == null)return;
            if(indexArr == null)
            {
                len = s._subThread.length;
                while(--len>-1)            
                {
                    if(s._subThread[len])
                        s._subThread[len].clear();
                }
                s._subThread.length = 0;
            }
            else
            {
                len = indexArr.length;
                while(--len>-1)            
                    s._subThread[indexArr[len]].clear();
            }
            
        }
        /**线程是否已经初始化*/
        public get inited():boolean
        {
            return this._inited;
        }
        public init(variables:any=null):void
        {
            let s= this;     
            if(s._inited)return;
            s._inited = true;   
            s.varObj = variables?variables:[];              
        }
        /**线程变量定义集*/
        public getVariable(n:string):any
        {
            return this.varObj[n];
        }        
        public excEnd(returnValue:any):void
        {
            let s = this;
            if(s.isEnd)return;
            s.returnValue = returnValue;            
            s.isEnd = true;
            s._costTime = s._runStartTime>0?Date.now() - s._runStartTime:0;
            if(s._excCall!=null)
            {                
                s._excCall.call(s._excCallObj, s);                
                s._excCall = s._excCallObj = null;
            }
            s.varObj = null;
            // Log.writeLog((s._parentThread?"子级":"父级")+"线程"+s._id+"执行完成用时:" + s._costTime + "ms");
            if(s._parentThread)                            
                s._parentThread.next();
        }
        /**线程是否执行超时*/
        public isTimeout():boolean
        {
            let s= this;
            if(Date.now() - s._excTime > s._cpuTime)
            {   
                console.error("线程超时，id:" + s._id);
                if(Date.now() - s._runStartTime > 5000)
                    console.error("线程耗时过长，id:" + s._id);
                return true;
            }                
            return false;
        }
        public next():void
        {
            let s = this;
            if(s._destroyed)return;
            if(s._globalThis && s._globalThis._destroyed)return;//调用方已经被销毁
            if(s.isEnd)return;            
            s._excTime = Date.now();
            if(s._timeId > -1)
                TimeManager.unTimeOut(s._timeId, s.next, s);
            s._timeId = TimeManager.timeOut(s.next, s, 16);
            s._func.apply(s._globalThis,s._params);                            
        }        
        public destroy():void
        {
            let s= this;
            if(s._destroyed)return;
            s._destroyed = true;
            s.clear();
            delete Thread.threads[s._id];
        }
        public clear():void
        {
            let s= this;            
            s._inited = false;
            s.isEnd = s._running = false;
            s._params = s.varObj = s._globalThis = s._func = null;            
            s._excCallObj = s._excCall = null;
            if(s._timeId > -1)
            {
                TimeManager.unTimeOut(s._timeId, s.next, s);
                s._timeId = -1;
            }            
            s.clearSubThread();
        }
        public get running():boolean
        {
            return this._running;
        }
        public get params():any[]
        {
            return this._params;
        }
    }
}
/**线程函数说明---------------
 * 线程函数拥有判断执行超时，中断后，延迟到下一帧继续执行的功能，有3个特点
 * 1、函数内需要保持数据的变量由线程定义初始化
 * 2、函数内由线程判断超时跳出，以及函数执行分阶段判断
 * 3、函数内可再次执行线程函数待子级线程执行完毕再继续执行
function thread(){          
    let element:any[];            
    let thread:Thread;
    let varObj:any;
    //从参数列表最后一个取出线程对象
    thread = arguments[arguments.length - 1];
    //初始化定义线程函数变量
    if(!thread.inited)thread.init({        
        result:false,
        index:0,
        len:NaN
    });
    varObj = thread.varObj;
    //阶段1执行，完成后阶段+1，判断是否超时，超时则跳出，不超时则继续
    if(thread.step == 0)
    {                
        s.clearMohuBagItems();
        ++thread.step;
        if(thread.isTimeout())
            return;
    }
    if(thread.step == 1)
    {       
        varObj.len = s._allInfo.length;
        for (; varObj.index < varObj.len;) 
        {
            //假如此时执行另外一个线程函数，我们通过子线程来执行，如果启动成功则等待子线程返回结果来激活当前线程的继续执行
            if(thread.runSubThread(0,s.sub_Thread,s,[],3))
                return;
            varObj.result = thread.getSubThread(0).returnValue;
            if (varObj.result) 
            {

            }
            //如果使用了子线程，则记得必须在得到子线程结果之后，清理子线程，否则子线程一直存在，则无法再进入子线程执行
            thread.clearSubThread();
            ++varObj.index;
            //for循环执行大量的时候，我们需要判断超时退出，分时间片执行剩下的部分，下个时间片线程函数会再次进入执行剩下部分
            if(thread.isTimeout())
                return;
        }
    }
    //当函数执行结束，需调用线程执行结束，否则将导致线程一直存在，我们可以传出一个结果给外部
    thread.excEnd(varObj.result);
}
 * -------------*/
